package zeno.project.springboot.authentication;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import zeno.project.springboot.constant.SystemConstant;
import zeno.project.springboot.dao.SysUserMapper;
import zeno.project.springboot.entity.system.SysUser;

import java.util.HashSet;
import java.util.Set;

/**
 * @author ZhiYong
 * @ClassName MyRealm.java
 * @Description 自定义realm
 * @createTime 2021/04/17 21:04:00
 * 需要继承 AuthorizingRealm 类，因为该类封装了很多方法，它也是一步步继承自 Realm 类的，继承了 AuthorizingRealm 类后，需要重写两个方法
 */
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 访问接口时的权限认证——授权
     * 用户身份认证后访问资源还需要获取权限，在此授权给用户，无权限则被限制访问，跳转到指定页面
     * @param principalCollection 认证授权信息
     * @return result
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取登录名
        String account = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 给该用户设置角色，角色信息存在t_role表中取
        Set<String> roleCodes = sysUserMapper.findRolesByAccount(account);
        authorizationInfo.setRoles(roleCodes);
        // 给该用户设置权限，权限信息存在t_permission表中取
        authorizationInfo.setStringPermissions(roleCodes.isEmpty() ? new HashSet<>() : sysUserMapper.findPermissionsByAccount(roleCodes));
        return authorizationInfo;
    }

    /**
     * 登陆时的登陆认证
     * 未登录的用户需要进行身份认证，即指定某些页面必须登陆认证
     * @param authenticationToken 登录token
     * @return result
     * @throws AuthenticationException AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 根据token获取用户名，如果您不知道该该token怎么来的，先可以不管，下文会解释
        String account = (String) authenticationToken.getPrincipal();
        // 根据用户名从数据库中查询该用户
        SysUser sysUser = sysUserMapper.getByAccount(account);
        if(sysUser != null) {
            // 把当前用户存到session中
            SecurityUtils.getSubject().getSession().setAttribute(SystemConstant.USER_SESSION, sysUser);
            // 传入用户名和密码进行身份认证，并返回认证信息
            return new SimpleAuthenticationInfo(sysUser.getAccount(), sysUser.getPassword(), "myRealm");
        } else {
            return null;
        }
    }
}
